package com.dd.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.common.convert.SysUserConvert;
import com.dd.common.dto.system.user.SysUserQueryDTO;
import com.dd.common.dto.system.user.SysUserUpdateDTO;
import com.dd.common.entity.SysUser;
import com.dd.common.entity.SysUserDept;
import com.dd.common.entity.SysUserPosition;
import com.dd.common.entity.SysUserRole;
import com.dd.common.enums.ErrorEnum;
import com.dd.common.exception.BusinessException;
import com.dd.common.mapper.SysUserDeptMapper;
import com.dd.common.mapper.SysUserMapper;
import com.dd.common.mapper.SysUserPositionMapper;
import com.dd.common.mapper.SysUserRoleMapper;
import com.dd.common.pojo.dto.PageDTO;
import com.dd.common.service.SysUserService;
import com.dd.common.utils.PageResult;
import com.dd.common.vo.MenuVO;
import com.dd.common.vo.SysUserAuthInfoVO;
import com.dd.common.vo.SysUserDetailVO;
import com.dd.common.vo.SysUserVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author cheng
 * @description 针对表【c_sys_user(系统用户表)】的数据库操作Service实现
 * @createDate 2025-08-23 17:00:07
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
        implements SysUserService {

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysUserDeptMapper sysUserDeptMapper;

    @Resource
    private SysUserPositionMapper sysUserPositionMapper;

    @Resource
    private SysUserConvert sysUserConvert;

    @Override
    public List<String> getSysUserRoles(Long userId) {
        return sysUserMapper.selectRoleCodesByUserId(userId);
    }

    @Override
    public List<String> getSysUserPermissions(Long userId) {
        return sysUserMapper.selectPermissionsByUserId(userId);
    }

    @Override
    public SysUserAuthInfoVO getSysUserAuthInfo(Long userId) {
        SysUserAuthInfoVO authInfo = new SysUserAuthInfoVO();

        // 1. 菜单树
        List<MenuVO> menuTree = getUserMenuTree(userId);
        authInfo.setMenus(menuTree);

        // 2. 权限标识（按钮权限）
        List<String> permissions = getSysUserPermissions(userId);
        authInfo.setPermissions(permissions);

        // 3. 角色编码
        List<String> roles = getSysUserRoles(userId);
        authInfo.setRoles(roles);

        return authInfo;
    }

    @Override
    public List<SysUserVO> listQuery(SysUserQueryDTO dto) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>()
                .like(StringUtils.hasText(dto.getUsername()), SysUser::getUsername, dto.getUsername())
                .like(StringUtils.hasText(dto.getNickname()), SysUser::getNickname, dto.getNickname())
                .like(StringUtils.hasText(dto.getRealName()), SysUser::getRealName, dto.getRealName())
                .eq(dto.getGender() != null, SysUser::getGender, dto.getGender())
                .eq(dto.getStatus() != null, SysUser::getStatus, dto.getStatus())
                .ge(dto.getCreatedAtStart() != null, SysUser::getCreateTime, dto.getCreatedAtStart())
                .le(dto.getCreatedAtEnd() != null, SysUser::getCreateTime, dto.getCreatedAtEnd())
                .ge(dto.getUpdatedAtStart() != null, SysUser::getUpdateTime, dto.getUpdatedAtStart())
                .le(dto.getUpdatedAtEnd() != null, SysUser::getUpdateTime, dto.getUpdatedAtEnd())
                .orderByAsc(SysUser::getId);

        return sysUserMapper.selectList(wrapper).stream().map(sysUser -> sysUserConvert.entityToVO(sysUser)).collect(Collectors.toList());
    }

    @Override
    public PageResult<SysUserVO> pageQuery(PageDTO pageDTO, SysUserQueryDTO dto) {
        // 1. 构建分页对象
        Page<SysUser> page = Page.of(pageDTO.getCurrent(), pageDTO.getSize());

        // 2. 使用 MP 的条件自动判空机制构建查询，并且使用子查询inSql进行连表查询
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>()
                .like(StringUtils.hasText(dto.getUsername()), SysUser::getUsername, dto.getUsername())
                .like(StringUtils.hasText(dto.getNickname()), SysUser::getNickname, dto.getNickname())
                .like(StringUtils.hasText(dto.getRealName()), SysUser::getRealName, dto.getRealName())
                .eq(dto.getGender() != null, SysUser::getGender, dto.getGender())
                .eq(dto.getStatus() != null, SysUser::getStatus, dto.getStatus())
//                .eq(dto.getRoleId() != null, SysUser::getRoleId, dto.getRoleId())
//                .eq(dto.getDeptId() != null, SysUser::getDeptId, dto.getDeptId())
//                .eq(dto.getPositionId() != null, SysUser::getPositionId, dto.getPositionId())
                .ge(dto.getCreatedAtStart() != null, SysUser::getCreateTime, dto.getCreatedAtStart())
                .le(dto.getCreatedAtEnd() != null, SysUser::getCreateTime, dto.getCreatedAtEnd())
                .ge(dto.getUpdatedAtStart() != null, SysUser::getUpdateTime, dto.getUpdatedAtStart())
                .le(dto.getUpdatedAtEnd() != null, SysUser::getUpdateTime, dto.getUpdatedAtEnd())
                .inSql(dto.getRoleId() != null, SysUser::getId,
                        "SELECT user_id FROM c_sys_user_role WHERE role_id = " + dto.getRoleId())
                .inSql(dto.getDeptId() != null, SysUser::getId,
                        "SELECT user_id FROM c_sys_user_dept WHERE dept_id = " + dto.getDeptId())
                .inSql(dto.getPositionId() != null, SysUser::getId,
                        "SELECT user_id FROM c_sys_user_position WHERE position_id = " + dto.getPositionId())
                .orderByAsc(SysUser::getId);

        // 3. 执行查询
        IPage<SysUser> result = sysUserMapper.selectPage(page, wrapper);
        // 4. 转换为 VO 分页结果
        List<SysUserVO> list = result.getRecords().stream().map(sysUserConvert::entityToVO).collect(Collectors.toList());
        return PageResult.iPageHandle(result.getTotal(), result.getCurrent(), result.getSize(), list);
    }

    /**
     * 修改用户信息
     * 默认情况下，每个数据库操作都是独立的事务。这里涉及多个数据库操作，需要使用 @Transactional 注解进行事务管理
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(SysUserUpdateDTO dto) {
        Long userId = dto.getId();
        if (userId == null) throw new BusinessException(ErrorEnum.PARAMS_MISSING, "用户ID不能为空");


        // 1. 检查用户是否存在
        SysUser existingUser = sysUserMapper.selectById(userId);
        if (existingUser == null) throw new BusinessException(ErrorEnum.USER_NOT_FOUND);

        // 2. 构建更新条件（避免直接更新所有字段）
        LambdaUpdateWrapper<SysUser> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SysUser::getId, userId)
                .set(dto.getUsername() != null, SysUser::getUsername, dto.getUsername())
                .set(dto.getEmail() != null, SysUser::getEmail, dto.getEmail())
                .set(dto.getPhone() != null, SysUser::getPhone, dto.getPhone())
                .set(dto.getNickname() != null, SysUser::getNickname, dto.getNickname())
                .set(dto.getRealName() != null, SysUser::getRealName, dto.getRealName())
                .set(dto.getGender() != null, SysUser::getGender, dto.getGender())
                .set(dto.getAvatar() != null, SysUser::getAvatar, dto.getAvatar())
                .set(dto.getStatus() != null, SysUser::getStatus, dto.getStatus());

        // 第一个参数 entity：可以传 null，因为更新字段都在 wrapper 中通过 set() 指定。
        // 第二个参数 wrapper：包含 SET 字段和 WHERE 条件。
        // 所以你不需要构造一个完整的 SysUser 对象去 updateById，避免了 null 覆盖问题（把 null 更新到数据库）。
        sysUserMapper.update(null, updateWrapper);

        // 3. 更新角色关系（null 不处理，[] 清空，[x,y] 替换）
        if (dto.getRoleIds() != null) {
            sysUserRoleMapper.deleteById(userId); // 清空旧角色
            if (!dto.getRoleIds().isEmpty()) {
                List<SysUserRole> userRoles = dto.getRoleIds().stream()
                        .map(roleId -> {
                            SysUserRole userRole = new SysUserRole();
                            userRole.setUserId(userId);
                            userRole.setRoleId(roleId);
                            return userRole;
                        })
                        .collect(Collectors.toList());
                sysUserRoleMapper.insert(userRoles);
            }
        }

        // 4. 更新部门关系
        if (dto.getDeptIds() != null) {
            sysUserDeptMapper.deleteById(userId);
            if (!dto.getDeptIds().isEmpty()) {
                List<SysUserDept> userDepts = dto.getDeptIds().stream()
                        .map(deptId -> {
                            SysUserDept userDept = new SysUserDept();
                            userDept.setUserId(userId);
                            userDept.setDeptId(deptId);
                            return userDept;
                        })
                        .collect(Collectors.toList());
                sysUserDeptMapper.insert(userDepts);
            }
        }

        // 5. 更新职位关系
        if (dto.getPositionIds() != null) {
            sysUserPositionMapper.deleteById(userId);
            if (!dto.getPositionIds().isEmpty()) {
                List<SysUserPosition> userPositions = dto.getPositionIds().stream()
                        .map(posId -> {
                            SysUserPosition userPosition = new SysUserPosition();
                            userPosition.setUserId(userId);
                            userPosition.setPositionId(posId);
                            return userPosition;
                        })
                        .collect(Collectors.toList());
                sysUserPositionMapper.insert(userPositions);
            }
        }

        return true;
    }

    @Override
    public SysUserDetailVO detail(Long id) {
        SysUser user = sysUserMapper.selectById(id);

        List<Long> roleIds = sysUserRoleMapper
                .selectList(new LambdaQueryWrapper<>(SysUserRole.class)
                        .eq(SysUserRole::getUserId, id))
                .stream().map(SysUserRole::getRoleId).collect(Collectors.toList());

        List<Long> deptIds = sysUserDeptMapper
                .selectList(new LambdaQueryWrapper<>(SysUserDept.class)
                        .eq(SysUserDept::getUserId, id))
                .stream().map(SysUserDept::getDeptId).collect(Collectors.toList());

        List<Long> positionIds = sysUserPositionMapper
                .selectList(new LambdaQueryWrapper<>(SysUserPosition.class)
                        .eq(SysUserPosition::getUserId, id))
                .stream().map(SysUserPosition::getPositionId).collect(Collectors.toList());

        SysUserDetailVO vo = sysUserConvert.entityToDetailVO(user);
        vo.setRoleIds(roleIds);
        vo.setDeptIds(deptIds);
        vo.setPositionIds(positionIds);
        return vo;
    }

    @Override
    public List<MenuVO> getUserMenuTree(Long userId) {
        // 1. 查询用户有权限的菜单列表
        List<MenuVO> menuList = sysUserMapper.selectMenuListByUserId(userId);

        // 2. 构建树形结构
        return buildMenuTree(menuList);
    }


    /**
     * 构建菜单树：将扁平列表转为父子结构
     */
    private List<MenuVO> buildMenuTree(List<MenuVO> menus) {
        if (menus == null || menus.isEmpty()) {
            return new ArrayList<>();
        }

        // 使用 Map 提升查找效率
        Map<Long, MenuVO> menuMap = menus.stream()
                .collect(Collectors.toMap(MenuVO::getId, menu -> menu));

        List<MenuVO> rootNodes = new ArrayList<>();

        for (MenuVO menu : menus) {
            Long parentId = menu.getParentId();
            if (parentId == 0) {
                // 一级菜单
                rootNodes.add(menu);
            } else {
                MenuVO parent = menuMap.get(parentId);
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(menu);
                }
            }
        }

        // 按 sort 排序
        rootNodes.sort(Comparator.comparing(MenuVO::getSort));
        rootNodes.forEach(this::sortChildren);
        return rootNodes;
    }

    /**
     * 递归对子菜单排序
     */
    private void sortChildren(MenuVO node) {
        if (node.getChildren() != null) {
            node.getChildren().sort(Comparator.comparing(MenuVO::getSort));
            node.getChildren().forEach(this::sortChildren);
        }
    }
}




